﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Net;
using System.IO;
using System.Threading;

namespace Collector
{
    /// <summary>
    /// 服务器的文件种类
    /// </summary>
    public enum FtpFileType
    {
        File,   　　  //文件
        Directory,　  //文件夹
        Other,   　　 //其他（文件、文件夹以外）
        All           //所有
    }
    /// <summary>
    /// 服务器文件夹的属性（绝对路径，
    /// IP，URL，路线文件夹）等父文件夹，除相对路径
    /// </summary>
    public enum FtpRemoteDirOption
    {
        UrlOpposite = 0,
        IpOpposite = 1,
        CurWorkDirOpposite = 2,
        Absolutely = 3,
    }

    public enum FtpTransType
    {
        ASCII = 0,
        BINARY = 1,
        EBCDIC = 2
    }

    public enum FtpDataTransMode
    {
        Port = 0,
        Pasv = 1,
        All = 2
    }

    public class FtpFileInfo
    {
        public String FileName { get; set; }

        public long fileSize { get; set; }

        public FtpFileType FileType { get; set; }

        public String Perssion { get; set; }

        public List<FtpFileInfo> FileList { get; set; }

        public String FileRemotePath { get; set; }

        public FtpRemoteDirOption FilePathType { get; set; }


        public DateTime ModTime { get; set; }

        #region "初期化関数"

        /// <summary>
        /// 
        /// </summary>
        public FtpFileInfo()
            : this("", FtpFileType.All, 0, "", FtpRemoteDirOption.Absolutely)
        {
        }

        public FtpFileInfo(String curFileName,
                         FtpFileType curFiletype,
                         long curFileSize,
                         String curFileRemotePath,
                           FtpRemoteDirOption curFilePathType,
                    String curPerssion)
            : this(curFileName,
                   curFiletype,
                   curFileSize,
                   curFileRemotePath,
                   curFilePathType, null,
                   curPerssion, default(DateTime))
        {
        }

        public FtpFileInfo(String curFileName,
                        FtpFileType curFiletype,
                        long curFileSize,
                           String curFileRemotePath,
                           FtpRemoteDirOption curFilePathType)
            : this(curFileName,
                   curFiletype,
                   curFileSize,
                   curFileRemotePath,
                   curFilePathType, null, "", default(DateTime))
        {
        }

        public FtpFileInfo(string curFileName,
                       FtpFileType curFiletype,
                       long curFileSize,
                       String curFileRemotePath,
                           FtpRemoteDirOption curFilePathType,
                         List<FtpFileInfo> curList,
                         String curPerssion,
                         DateTime curModTime)
        {
            this.FileName = curFileName;
            this.fileSize = curFileSize;
            this.FileType = curFiletype;
            this.Perssion = curPerssion;
            this.FileRemotePath = curFileRemotePath;
            this.FilePathType = curFilePathType;
            this.FileList = new List<FtpFileInfo>();
            this.ModTime = curModTime;
            if (curList != null)
            {
                this.FileList.AddRange(curList.GetRange(0, curList.Count));
            }
        }

        public FtpFileInfo(string curFileName,
                          FtpFileType curFiletype,
                          long curFileSize,
                          String curFileRemotePath,
                           FtpRemoteDirOption curFilePathType,
                          List<FtpFileInfo> curList)
            : this(curFileName,
                curFiletype,
                curFileSize,
                curFileRemotePath,
                curFilePathType,
                curList, "", default(DateTime))
        {
        }

    }


    public class FtpCodeMsg
    {
        String StrCode;
        String StrName;
        String StrComment;
        List<FtpCodeMsg> curListDetail;

        public String Code
        {
            get
            {
                return StrCode;
            }
            set
            {
                StrCode = value;
            }
        }

        public String Name
        {
            get
            {
                return StrName;
            }
            set
            {
                StrName = value;
            }
        }

        public String Comment
        {
            get
            {
                return StrComment;
            }
            set
            {
                StrComment = value;
            }
        }

        public List<FtpCodeMsg> DetailList
        {
            get
            {
                return curListDetail;
            }
            set
            {
                curListDetail = new List<FtpCodeMsg>();
                if (value != null)
                {
                    curListDetail.AddRange(value.GetRange(0, value.Count));
                }
            }

        }

        public FtpCodeMsg()
            : this("", "", null, "")
        {
        }

        public FtpCodeMsg(String curCode,
                          String curName)
            : this(curCode, curName, null, "")
        {
        }

        public FtpCodeMsg(String curCode,
                        String curName,
                          FtpCodeMsg[] curDetailArray)
            : this(curCode, curName, curDetailArray, "")
        {
        }

        public FtpCodeMsg(String curCode,
                        String curName,
                         String curComment)
            : this(curCode, curName, null, curComment)
        {
        }

        public FtpCodeMsg(String curCode,
                          String curName,
                          FtpCodeMsg[] curDetailArray,
                          String curComment)
        {
            this.Code = curCode;
            this.Name = curName;
            this.Comment = curComment;
            this.DetailList = null;
            if (curDetailArray != null)
            {
                this.DetailList.AddRange(curDetailArray);
            }

        }

        public FtpCodeMsg GetDetailByCode(
                                 String curCode)
        {
            return this.DetailList.Find(delegate(FtpCodeMsg curObj)
            {
                return curObj.Name.Equals(curCode);
            });
        }

        public FtpCodeMsg GetSubDetailByCode(
                                 String curCode)
        {
            FtpCodeMsg curObjItem = this.DetailList.Find(delegate(FtpCodeMsg curObj)
            {
                return curObj.Code.Equals(curCode);
            });
            if (curObjItem != null)
            {
                curObjItem = curObjItem.GetDetailByCode(curCode);
            }
            return curObjItem;
        }

        public String toString()
        {
            StringBuilder curStr = new StringBuilder();
            curStr.Append(@"[");
            curStr.Append(this.Code);
            curStr.Append(@"]:[");
            curStr.Append(this.Name);
            curStr.Append(@"]:(");
            curStr.Append(this.Comment);
            curStr.Append(@")");

            return curStr.ToString();
        }
    }


    public class FtpCommand : FtpCodeMsg
    {

        public FtpCommand()
            : this("", "", null, "")
        {
        }

        public FtpCommand(String curCmd,
                          String curCmdName)
            : this(curCmd, curCmdName, null, "")
        {
        }

        public FtpCommand(String curCmd,
                        String curCmdName,
                          FtpCodeMsg[] curRepMsgArry)
            : this(curCmd, curCmdName, curRepMsgArry, "")
        {
        }

        public FtpCommand(String curCmd,
                        String curCmdName,
                         String curComment)
            : this(curCmd, curCmdName, null, curComment)
        {
        }

        public FtpCommand(String curCmd,
                          String curCmdName,
                          FtpCodeMsg[] curRepMsgArry,
                          String curComment)
            : base(curCmd,
            curCmdName,
            curRepMsgArry,
            curComment)
        {

        }

    }

    public static class FtpCommon
    {

        public static FtpCodeMsg TRAN_ASCII = new FtpCodeMsg("A", "ASCII", "数据通信种类");

        public static FtpCodeMsg TRAN_BINARY = new FtpCodeMsg("I", "BINARY", "数据通信种类");

        public static FtpCodeMsg TRAN_EBCDIC = new FtpCodeMsg("E", "EBCDIC", "数据通信种类");

        public static FtpCodeMsg TRAN_A = new FtpCodeMsg(FtpTransType.ASCII.ToString(),
        "ASCII", new FtpCodeMsg[] { TRAN_ASCII }, "数据通信种类");

        public static FtpCodeMsg TRAN_I = new FtpCodeMsg(FtpTransType.BINARY.ToString(), "BINARY", new FtpCodeMsg[] { TRAN_BINARY }, "数据通信种类");

        public static FtpCodeMsg TRAN_E = new FtpCodeMsg(FtpTransType.EBCDIC.ToString(), "EBCDIC", new FtpCodeMsg[] { TRAN_EBCDIC }, "数据通信种类");

        public static FtpCodeMsg TRAN_TYPELIST = new FtpCodeMsg("TRANS_TYPELIST", "TRANS_TYPELIST", new FtpCodeMsg[] { TRAN_A, TRAN_I, TRAN_E }, "数据通信种类");

        public static FtpCodeMsg REP_110 = new FtpCodeMsg("110", "110", "Restart marker reply");
        public static FtpCodeMsg REP_120 = new FtpCodeMsg("120", "120", "Service ready in nnn minutes");
        public static FtpCodeMsg REP_125 = new FtpCodeMsg("125", "125", "Data connection already open; transfer starting");
        public static FtpCodeMsg REP_150 = new FtpCodeMsg("150", "150", "File status okay; about to open data connection");
        public static FtpCodeMsg REP_200 = new FtpCodeMsg("200", "200", "Command okay");
        public static FtpCodeMsg REP_202 = new FtpCodeMsg("202", "202", "Command not implemented, superfluous at this site");
        public static FtpCodeMsg REP_211 = new FtpCodeMsg("211", "211", "System status, or system help reply");
        public static FtpCodeMsg REP_212 = new FtpCodeMsg("212", "212", "Directory status");
        public static FtpCodeMsg REP_213 = new FtpCodeMsg("213", "213", "File status");
        public static FtpCodeMsg REP_214 = new FtpCodeMsg("214", "214", "Help message");
        public static FtpCodeMsg REP_215 = new FtpCodeMsg("215", "215", "NAME system type.Where NAME is an official system name from the list in the Assigned Numbers document");
        public static FtpCodeMsg REP_220 = new FtpCodeMsg("220", "220", "Service ready for new user");
        public static FtpCodeMsg REP_221 = new FtpCodeMsg("221", "221", "Service closing control connection.  Logged out if appropriate");
        public static FtpCodeMsg REP_225 = new FtpCodeMsg("225", "225", "Data connection open; no transfer in progress");
        public static FtpCodeMsg REP_226 = new FtpCodeMsg("226", "226", "Closing data connection.  Requested file action successful (for example, file transfer or file abort)");
        public static FtpCodeMsg REP_227 = new FtpCodeMsg("227", "227", "Entering Passive Mode (h1,h2,h3,h4,p1,p2)");
        public static FtpCodeMsg REP_230 = new FtpCodeMsg("230", "230", "User logged in, proceed");
        public static FtpCodeMsg REP_250 = new FtpCodeMsg("250", "250", "Requested file action okay, completed");
        public static FtpCodeMsg REP_257 = new FtpCodeMsg("257", "257", "PATHNAME created");
        public static FtpCodeMsg REP_331 = new FtpCodeMsg("331", "331", "User name okay, need password");
        public static FtpCodeMsg REP_332 = new FtpCodeMsg("332", "332", "Need account for login");
        public static FtpCodeMsg REP_350 = new FtpCodeMsg("350", "350", "Requested file action pending further information");
        public static FtpCodeMsg REP_421 = new FtpCodeMsg("421", "421", "Service not available, closing control connection");
        public static FtpCodeMsg REP_425 = new FtpCodeMsg("425", "425", "Can't open data connection");
        public static FtpCodeMsg REP_426 = new FtpCodeMsg("426", "426", "Connection closed; transfer aborted");
        public static FtpCodeMsg REP_450 = new FtpCodeMsg("450", "450", "Requested file action not taken");
        public static FtpCodeMsg REP_451 = new FtpCodeMsg("451", "451", "Requested action aborted: local error in processing");
        public static FtpCodeMsg REP_452 = new FtpCodeMsg("452", "452", "Requested action not taken.Insufficient storage space in system");
        public static FtpCodeMsg REP_500 = new FtpCodeMsg("500", "500", "Syntax error, command unrecognized. This may include errors such as command line too long");
        public static FtpCodeMsg REP_501 = new FtpCodeMsg("501", "501", "Syntax error in parameters or arguments");
        public static FtpCodeMsg REP_502 = new FtpCodeMsg("502", "502", "Command not implemented");
        public static FtpCodeMsg REP_503 = new FtpCodeMsg("503", "503", "Bad sequence of commands");
        public static FtpCodeMsg REP_504 = new FtpCodeMsg("504", "504", "Command not implemented for that parameter");
        public static FtpCodeMsg REP_530 = new FtpCodeMsg("530", "530", "Not logged in");
        public static FtpCodeMsg REP_532 = new FtpCodeMsg("532", "532", "Need account for storing files");
        public static FtpCodeMsg REP_550 = new FtpCodeMsg("550", "550", "Requested action not taken.  File unavailable (e.g., file not found, no access)");
        public static FtpCodeMsg REP_551 = new FtpCodeMsg("551", "551", "Requested action aborted: page type unknown");
        public static FtpCodeMsg REP_552 = new FtpCodeMsg("552", "552", "Requested file action aborted. Exceeded storage allocation (for current directory or  dataset)");
        public static FtpCodeMsg REP_553 = new FtpCodeMsg("553", "553", "Requested action not taken.  File name not allowed");

        public static FtpCodeMsg REP_LIST = new FtpCodeMsg("REP_LIST", "REP_LIST",
                                    new FtpCodeMsg[]{
                                        REP_110,
                                        REP_120,
                                        REP_125,
                                        REP_150,
                                        REP_200,
                                        REP_202,
                                        REP_211,
                                        REP_212,
                                        REP_213,
                                        REP_214,
                                        REP_215,
                                        REP_220,
                                        REP_221,
                                        REP_225,
                                        REP_226,
                                        REP_227,
                                        REP_230,
                                        REP_250,
                                        REP_257,
                                        REP_331,
                                        REP_332,
                                        REP_350,
                                        REP_421,
                                        REP_425,
                                        REP_426,
                                        REP_450,
                                        REP_451,
                                        REP_452,
                                        REP_500,
                                        REP_501,
                                        REP_502,
                                        REP_503,
                                        REP_504,
                                        REP_530,
                                        REP_532,
                                        REP_550,
                                        REP_551,
                                        REP_552,
                                        REP_553,
                                        }, "");


        public static FtpCommand CMD_ABOR = new FtpCommand("ABOR", "ABOR");

        public static FtpCommand CMD_ACCT = new FtpCommand("ACCT", "ACCT");

        public static FtpCommand CMD_ALLO = new FtpCommand("ALLO", "ALLO");

        public static FtpCommand CMD_APPE = new FtpCommand("APPE", "APPE");

        public static FtpCommand CMD_CDUP = new FtpCommand("CDUP", "CDUP");

        public static FtpCommand CMD_CWD = new FtpCommand("CWD", "CWD",
                                            new FtpCodeMsg[] { FtpCommon.REP_250 });

        public static FtpCommand CMD_CWD_MKD = new FtpCommand("CWD", "CWD",
                                              new FtpCodeMsg[] { FtpCommon.REP_250,
                                                              FtpCommon.REP_550  });

        public static FtpCommand CMD_DELE = new FtpCommand("DELE", "DELE",
                                            new FtpCodeMsg[] {FtpCommon.REP_200,
                                                              FtpCommon.REP_250,
                                                              FtpCommon.REP_550  });

        public static FtpCommand CMD_HELP = new FtpCommand("HELP", "HELP",
                                            new FtpCodeMsg[] {FtpCommon.REP_214,
                                                              FtpCommon.REP_200,
                                                              FtpCommon.REP_250,
                                                              FtpCommon.REP_500});

        public static FtpCommand CMD_LIST = new FtpCommand("LIST", "LIST",
                                            new FtpCodeMsg[] { FtpCommon.REP_150, FtpCommon.REP_125, FtpCommon.REP_226 });

        public static FtpCommand CMD_MODE = new FtpCommand("MODE", "MODE");

        public static FtpCommand CMD_MKD = new FtpCommand("MKD", "MKD",
                                            new FtpCodeMsg[] { FtpCommon.REP_550,
                                                              FtpCommon.REP_257});

        public static FtpCommand CMD_NLST = new FtpCommand("NLST", "NLST");

        public static FtpCommand CMD_NOOP = new FtpCommand("NOOP", "NOOP",
                                            new FtpCodeMsg[] { FtpCommon.REP_200,
                                                              FtpCommon.REP_250});

        public static FtpCommand CMD_PASS = new FtpCommand("PASS", "PASS",
                                   new FtpCodeMsg[] { FtpCommon.REP_230, 
                              　　　　　　　      　FtpCommon.REP_202 });

        public static FtpCommand CMD_PASV = new FtpCommand("PASV", "PASV",
                                      new FtpCodeMsg[] { FtpCommon.REP_227 });

        public static FtpCommand CMD_PORT = new FtpCommand("PORT", "PORT",
                                   new FtpCodeMsg[] { FtpCommon.REP_220, 
                              　　　　　　　      　FtpCommon.REP_200,
                              　　　　　　　      　FtpCommon.REP_250 });

        public static FtpCommand CMD_PWD = new FtpCommand("PWD", "PWD",
                                  new FtpCodeMsg[] { FtpCommon.REP_257, 
                          　　　　　　　            FtpCommon.REP_250});

        public static FtpCommand CMD_QUIT = new FtpCommand("QUIT", "QUIT");

        public static FtpCommand CMD_REIN = new FtpCommand("REIN", "REIN");

        public static FtpCommand CMD_REST = new FtpCommand("REST", "REST");

        public static FtpCommand CMD_RETR = new FtpCommand("RETR", "RETR",
                                        new FtpCodeMsg[]{
                                         FtpCommon.REP_150,
                                         FtpCommon.REP_125,
                                         FtpCommon.REP_226,
                                         FtpCommon.REP_250});

        public static FtpCommand CMD_RMD = new FtpCommand("RMD", "RMD",
                                        new FtpCodeMsg[]{
                                         FtpCommon.REP_250});

        public static FtpCommand CMD_RNFR = new FtpCommand("RNFR", "RNFR",
                                        new FtpCodeMsg[]{
                                         FtpCommon.REP_350,
                                         FtpCommon.REP_200,
                                         FtpCommon.REP_250});

        public static FtpCommand CMD_RNTO = new FtpCommand("RNTO", "RNTO",
                                        new FtpCodeMsg[]{ 
                                         FtpCommon.REP_200,
                                         FtpCommon.REP_250});

        public static FtpCommand CMD_SITE = new FtpCommand("SITE", "SITE");

        public static FtpCommand CMD_SMNT = new FtpCommand("SMNT", "SMNT");

        public static FtpCommand CMD_STAT = new FtpCommand("STAT", "STAT");

        public static FtpCommand CMD_STOR = new FtpCommand("STOR", "STOR"
                                            , new FtpCodeMsg[] { FtpCommon.REP_125, FtpCommon.REP_150 }
                                             );

        public static FtpCommand CMD_STOU = new FtpCommand("STOU", "STOU");

        public static FtpCommand CMD_STRU = new FtpCommand("STRU", "STRU");

        public static FtpCommand CMD_SYST = new FtpCommand("SYST", "SYST"
                                            , new FtpCodeMsg[] { FtpCommon.REP_215, FtpCommon.REP_200,
                                             FtpCommon.REP_250}
                                             );

        public static FtpCommand CMD_TYPE = new FtpCommand("TYPE", "TYPE"
                                            , new FtpCodeMsg[] { FtpCommon.REP_200 }
                                             );

        public static FtpCommand CMD_USER = new FtpCommand("USER", "USER",
                                          new FtpCodeMsg[] { FtpCommon.REP_230,
                                                            FtpCommon.REP_331 }
                                         );

        public static FtpCommand CMD_SIZE = new FtpCommand("SIZE", "SIZE"
                                            , new FtpCodeMsg[] { FtpCommon.REP_213 }
                                             );

        public static FtpCommand CMD_MDTM = new FtpCommand("MDTM", "MDTM"
                                            , new FtpCodeMsg[] { FtpCommon.REP_213 }
                                             );
        #endregion




        public static FtpCodeMsg ERR_ISNULL = new FtpCodeMsg("001", "登录情报未设定IP [{0}], User [{1}], Pwd [{2}]");
        public static FtpCodeMsg ERR_CONNECTERR = new FtpCodeMsg("002", "指令执行错误。[Command:{0}][Reply:{1}]");
        public static FtpCodeMsg ERR_GETDATASOCKETERR = new FtpCodeMsg("003", "数据传输IP地址分析错误[MSG:{0}]");
        public static FtpCodeMsg ERR_CREATEDATASOCKETERR = new FtpCodeMsg("004", "据传输插座制作错误[IPADR:{0}：{1}] ({2})");
        public static FtpCodeMsg ERR_GETLOCALIP = new FtpCodeMsg("005", "本地IP地址取得失败。[IPADR:{0}]");
        public static FtpCodeMsg ERR_RENAMEFILE_ISNULL = new FtpCodeMsg("006", "文件名称变更的场合，变更前后文件名未设定");
        public static FtpCodeMsg ERR_PARAM_ISNULL = new FtpCodeMsg("007", "文件名未指定");

    }

    public class FtpClient
    {

        //private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        /// <summary>
        /// List of REGEX formats for different FTP server listing formats
        /// </summary>
        /// <remarks>
        /// The first three are various UNIX/LINUX formats, fourth is for MS FTP
        /// in detailed mode and the last for MS FTP in 'DOS' mode.
        /// I wish VB.NET had support for Const arrays like C# but there you go
        /// </remarks>
        private static string[] c_ListRegexFormats = new string[] { 
            "(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\S+\\s+\\S+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{4})\\s+(?<name>.+)", 
            "(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\d+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{4})\\s+(?<name>.+)", 
            "(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\d+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{1,2}:\\d{2})\\s+(?<name>.+)", 
            "(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})\\s+\\d+\\s+\\S+\\s+\\S+\\s+(?<size>\\d+)\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{1,2}:\\d{2})\\s+(?<name>.+)", 
            "(?<dir>[\\-d])(?<permission>([\\-r][\\-w][\\-xs]){3})(\\s+)(?<size>(\\d+))(\\s+)(?<ctbit>(\\w+\\s\\w+))(\\s+)(?<size2>(\\d+))\\s+(?<timestamp>\\w+\\s+\\d+\\s+\\d{2}:\\d{2})\\s+(?<name>.+)", 
            "(?<timestamp>\\d{2}\\-\\d{2}\\-\\d{2}\\s+\\d{2}:\\d{2}[Aa|Pp][mM])\\s+(?<dir>\\<\\w+\\>){0,1}(?<size>\\d+){0,1}\\s+(?<name>.+)" };

        private static string c_RegexDir = "dir";
        private static string c_RegexPer = "permission";
        private static string c_RegexSize = "size";
        private static string c_RegexTime = "timestamp";
        private static string c_RegexName = "name";


        private const string c_REGEX_STR_FTPADR = @"^(?<ftp>((F|f)(T|t)(P|p)://)?)((?<User>[^:]+):(?<Pwd>[^@]*)@)?(?<Address>([\w-]+\.)+[\w-]+)([:]?(?<Port>[\d]+))?(?<SubDir>(/[\w-./?%&=]*)?)$";
        private const string c_RegexFtp = "ftp";
        private const string c_RegexUser = "User";
        private const string c_RegexPwd = "Pwd";
        private const string c_RegexAdr = "Address";
        private const string c_RegexPort = "Port";
        private const string c_RegexSubDir = "SubDir";

        private const string c_REGEX_STR_IP = @"\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b";

        private const string c_REGEX_STR_IP_TRANS = @"(?<Address>(([01]?\d?\d|2[0-4]\d|25[0-5])\,){3}([01]?\d?\d|2[0-4]\d|25[0-5]))\,(?<Port>[0-9]{1,})\,(?<Port1>[0-9]{1,})";
        private const string c_RegexPort1 = "Port1";

        private const string c_REGEX_STR_REPCODE = @"^(?<Code>[0-9]{3})[^0-9]{1}(\S|\s)+$";
        private const string c_RepCode = "Code";


        private const string c_REGEX_STR_DEFAULTPATH = @"(?<Path>/{1}(((/{1}\.{1})?[a-zA-Z0-9 ]+/?)+(\.{1}[a-zA-Z0-9]{2,4})?)?)";
        private const string c_RepPath = "Path";


        private const string c_CTRLF = "\r\n";
        private const string c_LF = "\n";


        private const int RECONNECT_CNT = 3;


        private const int SLEEP_SECONDS = 10 * 1000;



        private const int c_BLOCK_SIZE = 1024;

        private const int c_DEFAULT_PORT = 21;




        private String StrHost;
        public String Host
        {
            get { return StrHost; }
        }

        private String StrHostUrl;
        public String HostUrl
        {
            get { return StrHostUrl; }
            set { StrHostUrl = value; }
        }

        private String StrPort;
        public Int32 Port
        {
            get
            {
                if (StrPort.Length > 0)
                {
                    return Int32.Parse(StrPort);
                }
                else
                {
                    return c_DEFAULT_PORT;
                };
            }
            set { StrPort = value.ToString(); }
        }

        private String StrRemotesubDir;
        public String RemotesubDir
        {
            get
            {
                return StrRemotesubDir;
            }
            set { StrRemotesubDir = value; }
        }

        private String StrRemoteCurSubDir;
        public String RemoteCurSubDir
        {
            get { return StrRemoteCurSubDir; }
        }

        private String StrRemoteHostUrlSubDir;
        public String RemoteHostUrlSubDir
        {
            get { return StrRemoteHostUrlSubDir; }
        }

        private String StrRemoteAbsolutDir;
        public String RemoteAbsolutDir
        {
            get { return StrRemoteAbsolutDir; }
        }

        private String StrLocalDir;

        public String LocalDir
        {
            get { return StrLocalDir; }
            set { StrLocalDir = value; }
        }

        private String StrUser;
        public String LoginUser
        {
            get { return StrUser; }
            set { StrUser = value; }
        }

        private String StrPassWord;
        public String PassWord
        {
            get { return StrPassWord; }
            set { StrPassWord = value; }
        }

        private Boolean blnConnected;

        public Boolean Connected
        {
            get { return blnConnected; }
        }

        private Socket objsocketControl;

        private Socket socketControl
        {

            get { return objsocketControl; }
            set { objsocketControl = value; }
        }

        private Socket objsocketListener;

        private Socket socketListener
        {

            get { return objsocketListener; }
            set { objsocketListener = value; }
        }

        private FtpTransType objTranType;
        public FtpTransType TranType
        {
            get { return objTranType; }
            set
            {
                objTranType = value;

                if (this.Connected)
                {
                    this.ExecCommand(FtpCommon.CMD_TYPE,
                              FtpCommon.TRAN_TYPELIST.GetSubDetailByCode(
                                           this.TranType.ToString()
                                           ).Code
                    );
                }
            }
        }

        private String strCmdRelayMsg;
        public String CmdRelayMsg
        {
            get { return strCmdRelayMsg; }
        }

        private String strCmdRelayFullMsg;
        public String CmdRelayFullMsg
        {
            get { return strCmdRelayFullMsg; }
        }


        private Boolean blnErrFlag;
        public Boolean ErrFlag
        {
            get
            {
                return blnErrFlag;
            }
        }

        private Boolean blnChildFolderDown;
        public Boolean ChildFolderDown
        {
            get
            {
                return blnChildFolderDown;
            }
            set { blnChildFolderDown = value; }
        }

        private Boolean blnDownLoadOverWrite;
        public Boolean DownLoadOverWrite
        {
            get
            {
                return blnDownLoadOverWrite;
            }
            set { blnDownLoadOverWrite = value; }
        }


        private FtpDataTransMode eumPasvMode;
        public FtpDataTransMode PasvMode
        {
            get
            {
                return eumPasvMode;
            }
            set
            {
                eumPasvMode = value;
            }
        }

        private int intLoopConnectCnt;
        public int LoopConnectCnt
        {
            get
            {
                return (intLoopConnectCnt <= 0 ?
                RECONNECT_CNT : intLoopConnectCnt);
            }
            set
            {
                intLoopConnectCnt = value;
            }
        }

        private int intRetryConnWaitTime;
        public int RetryConnWaitTime
        {
            get
            {
                return (intRetryConnWaitTime <= 0 ?
                      SLEEP_SECONDS : intRetryConnWaitTime);
            }
            set
            {
                intRetryConnWaitTime = value;
            }
        }


        private String strSystemInfo;
        public String SystemInfo
        {
            get
            {
                return strSystemInfo;
            }
        }




        private bool InitFtpClient()
        {
            Match curMatch = null, curMatchIp = null;
            bool ret = false;


            this.StrHost = "";

            if (!this.HostUrl.Trim().Equals(""))
            {
                //
                curMatch = RegexMatch(this.HostUrl,
                          new String[] { c_REGEX_STR_FTPADR });

                string curTemp = "";
                if (curMatch != null)
                {

                    curTemp = curMatch.Groups[c_RegexUser].Value.Trim();

                    if (!curTemp.Equals(""))
                    {
                        this.LoginUser = curTemp;
                    }

                    curTemp = curMatch.Groups[c_RegexPwd].Value.Trim();
                    if (!curTemp.Equals(""))
                    {
                        this.PassWord = curTemp;
                    }

                    curTemp = curMatch.Groups[c_RegexAdr].Value.Trim();
                    curMatchIp = RegexMatch(curTemp, new String[] { c_REGEX_STR_IP });

                    if (!curTemp.Equals("")
                         && (curMatchIp == null || !curMatchIp.Success))
                    {

                        IPAddress[] curIPAddress = Dns.GetHostEntry(curTemp).AddressList;
                        if (curIPAddress != null && curIPAddress.Length != 0)
                        {
                            curTemp = curIPAddress[0].ToString();
                        }
                    }

                    this.StrHost = curTemp;

                    curTemp = curMatch.Groups[c_RegexPort].Value.Trim();
                    if (!curTemp.Equals(""))
                    {
                        this.Port = Int32.Parse(curTemp);
                    }

                    curTemp = curMatch.Groups[c_RegexSubDir].Value.Trim();
                    this.StrRemoteHostUrlSubDir = (curTemp.Equals("") ? @"/" : curTemp);

                    if (!this.StrRemoteHostUrlSubDir.Equals(@"/")
                          && !this.StrRemoteHostUrlSubDir.EndsWith(@"/"))
                    {
                        this.StrRemoteHostUrlSubDir += @"/";
                    }
                }
            }

            if (this.RemotesubDir.Equals(""))
            {
                this.RemotesubDir = @"/";
            }
            if (!this.RemotesubDir.Equals(@"/")
                  && !this.RemotesubDir.EndsWith(@"/"))
            {
                this.RemotesubDir += @"/";
            }

            if (this.LocalDir.Equals(""))
            {
                this.LocalDir = System.IO.Directory.GetCurrentDirectory();
            }

            if (!this.Host.Equals("") && !this.LoginUser.Equals("")
                   && !this.PassWord.Equals(""))
            {
                ret = true;
            }

            this.LoopConnectCnt = RECONNECT_CNT;

            this.RetryConnWaitTime = SLEEP_SECONDS;

            this.strSystemInfo = "";
            //
            this.strCmdRelayFullMsg = "";
            return ret;
        }

        public FtpClient(
               )
            : this("",
                  "",
                  c_DEFAULT_PORT,
                  "",
                  "",
                  FtpTransType.BINARY,
                  "", FtpDataTransMode.All)
        {
        }

        public FtpClient(
                String curHostUrl,
                String curHostUser,
                String curHostPassWord
           )
            : this(curHostUrl,
                  "",
                  c_DEFAULT_PORT,
                  curHostUser,
                  curHostPassWord,
                  FtpTransType.BINARY,
                  "", FtpDataTransMode.All)
        {
        }

        public FtpClient(
             String curHostUrl,
             String curHostUser,
             String curHostPassWord,
             String curHostsubDir
        )
            : this(curHostUrl,
                  curHostsubDir,
                  c_DEFAULT_PORT,
                  curHostUser,
                  curHostPassWord,
                  FtpTransType.BINARY,
                  "", FtpDataTransMode.All)
        {
        }

        public FtpClient(
                String curHostUrl,
                String curHostsubDir,
                Int32 curPort,
                String curHostUser,
                String curHostPassWord,
                FtpTransType curTrans,
                String curLocalDir,
                 FtpDataTransMode curPasvMode)
        {

            this.HostUrl = (curHostUrl == null ? "" : curHostUrl);

            this.RemotesubDir = (curHostUrl == null ? "" : curHostsubDir);

            this.StrRemoteHostUrlSubDir = "";
            this.PasvMode = curPasvMode;

            this.StrRemoteCurSubDir = @"/";

            this.Port = (curHostUrl == null ? c_DEFAULT_PORT : curPort);
            //
            this.StrPort = c_DEFAULT_PORT.ToString();

            this.LoginUser = (curHostUser == null ? "anonymous" : curHostUser);

            this.PassWord = (curHostPassWord == null ? "anonymous" : curHostPassWord);

            this.TranType = curTrans;

            this.LocalDir = (curLocalDir == null ? "" : curLocalDir);

            this.StrRemoteAbsolutDir = "";
            this.blnConnected = false;

            Connect(false);
        }



        public void Connect()
        {
            this.Connect(true);
        }

        private void Connect(Boolean errFlag)
        {
            Match curMatch = null;
            int intRetray = this.LoopConnectCnt;

            if (this.blnConnected)
            {
                return;
            }

            this.InitFtpClient();

            if ((this.Host.Equals("") ||
                 this.LoginUser.Equals("")))
            {
                if (errFlag)
                {
                    throw (new Exception(String.Format(FtpCommon.ERR_ISNULL.Name,
                                           this.Host, this.LoginUser, this.PassWord)));
                }
                else
                {
                    return;
                }
            }
            while (true)
            {
                try
                {

                    CloseControlSocket();
                    intRetray--;

                    socketControl = new Socket(AddressFamily.InterNetwork,
                                                 SocketType.Stream, ProtocolType.Tcp);
                    //IpAdress 
                    IPEndPoint ServerIP = new IPEndPoint(IPAddress.Parse(this.Host), this.Port);

                    try
                    {
                        socketControl.Connect(ServerIP);
                    }
                    catch (Exception e)
                    {
                        throw new IOException(
                                 String.Format(FtpCommon.ERR_CONNECTERR.toString(), e.Message)
                                             );
                    }

                    ReadCmdReply();

                    CheckCmdStatus(ReturnCode(),
                          String.Format("Connect {0}:{1}@{2}:{3}",
                                       this.LoginUser,
                                       this.PassWord,
                                       this.Host,
                                       this.Port), new FtpCodeMsg[] { FtpCommon.REP_220 });

                    this.ExecCommand(FtpCommon.CMD_USER, this.LoginUser);

                    if (ReturnCode().Equals(FtpCommon.REP_331.Code))
                    {
                        this.ExecCommand(FtpCommon.CMD_PASS, this.PassWord);
                    }

                    this.ExecCommand(FtpCommon.CMD_PWD);

                    if ((curMatch =
                           this.RegexMatch(this.CmdRelayMsg,
                                new String[] { c_REGEX_STR_DEFAULTPATH })) != null)
                    {
                        this.StrRemoteCurSubDir = curMatch.Groups[c_RepPath].Value;

                        if (this.StrRemoteCurSubDir.Length > 0
                            && !this.StrRemoteCurSubDir.EndsWith(@"/"))
                        {
                            this.StrRemoteCurSubDir += @"/";
                        }
                    }


                    this.ExecCommand(FtpCommon.CMD_TYPE,
                                        FtpCommon.TRAN_TYPELIST.GetSubDetailByCode(
                                                     this.TranType.ToString()
                                                     ).Code
                               );


                    this.ExecCommand(FtpCommon.CMD_SYST);

                    this.strSystemInfo = this.CmdRelayMsg.Replace(this.ReturnCode(), "");

                    this.blnConnected = true;

                    this.blnErrFlag = false;

                    this.ChildFolderDown = false;

                    this.DownLoadOverWrite = true;

                    this.ChangeDir(@"/", FtpRemoteDirOption.CurWorkDirOpposite);

                    break;
                }
                catch (Exception e)
                {

                    if (string.IsNullOrWhiteSpace(this.CmdRelayMsg) && intRetray > 0)//this.CmdRelayMsg.Equals("")
                    {

                        ExceptionSleepWaiting();
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
        }

        public void DisConnect()
        {
            if (this.socketControl != null
                    && this.blnConnected)
            {

                ExecCommand(FtpCommon.CMD_QUIT);
            }
            CloseControlSocket();
        }

        private void CloseControlSocket()
        {
            if (this.socketControl != null)
            {
                this.socketControl.Close();
                this.socketControl = null;
            }
            if (this.socketListener != null)
            {
                this.socketListener.Close();
                this.socketListener = null;
            }
            this.blnConnected = false;
        }

        private void ExceptionSleepWaiting()
        {
            CloseControlSocket();
            Thread.Sleep(this.RetryConnWaitTime);
        }

        private String ExecCommand(FtpCommand curCmd, String[] Param)
        {
            StringBuilder CmdString = new StringBuilder();

            this.strCmdRelayFullMsg = "";

            CmdString.Append(curCmd.Name);

            if (Param != null)
            {
                for (int i = 0; i < Param.Length; i++)
                {
                    if (!Param[i].Trim().Equals(""))
                    {
                        CmdString.Append(" ");
                        CmdString.Append(Param[i].Trim());
                    }
                }
            }

            CmdString.Append(c_CTRLF);

            byte[] cmdBytes = Encoding.Default.GetBytes((CmdString.ToString()).ToCharArray());
            try
            {

                this.socketControl.Send(cmdBytes, cmdBytes.Length, 0);
            }
            catch (SocketException e)
            {
                throw new Exception(String.Format("{0} {1} {2}",
                                                  CmdString.ToString(),
                                                   e.Message,
                                                   e.StackTrace));
            }

            if (!curCmd.Name.Equals(FtpCommon.CMD_QUIT.Name))
            {
                ReadCmdReply();

                CheckCmdStatus(ReturnCode(),
                             CmdString.ToString(), curCmd.DetailList.ToArray());
            }

            return ReturnCode();
        }

        private String ExecCommand(FtpCommand curCmd, String Param)
        {
            return this.ExecCommand(curCmd,
                   new String[] { (Param == null ? "" : Param) }
                   );
        }

        private String ExecCommand(FtpCommand curCmd)
        {
            return ExecCommand(curCmd, "");
        }

        private String ReadCmdReply(int sleepTime)
        {
            int curSize = 0;
            Byte[] curGetBuffer = new byte[c_BLOCK_SIZE];
            StringBuilder strReplyMsg = new StringBuilder();
            String[] Message = null;
            String strSplit = "";

            this.strCmdRelayMsg = "";

            sleepTime = (sleepTime <= 0 ? 50 : sleepTime);

            while (true)
            {
                try
                {

                    curSize = this.socketControl.Receive(curGetBuffer, curGetBuffer.Length, 0);
                    strReplyMsg.Append(Encoding.ASCII.GetString(curGetBuffer, 0, curSize));

                    if (curSize < curGetBuffer.Length)
                    {
                        break;
                    }
                }
                catch (Exception e)
                {
                    this.DisConnect();

                    this.blnErrFlag = true;
                    throw (new System.Net.WebException(e.ToString()));
                }
            }
            Thread.Sleep(sleepTime);
            strSplit = c_LF;
            if (strReplyMsg.ToString().Contains(c_CTRLF))
            {
                strSplit = c_CTRLF;
            }
            Message = strReplyMsg.ToString().Split(strSplit.ToCharArray());


            if (Message.Length > 3)
            {
                this.strCmdRelayMsg = Message[Message.Length - 3].ToString();
            }
            else
            {
                this.strCmdRelayMsg = Message[0].ToString();
            }

            this.strCmdRelayFullMsg += strReplyMsg.ToString();

            if (!this.strCmdRelayMsg.Substring(3, 1).Equals(" "))
            {
                return ReadCmdReply(sleepTime);
            }
            return this.strCmdRelayMsg;
        }

        private String ReadCmdReply()
        {
            return ReadCmdReply(20);
        }

        private String ReturnCode()
        {
            String curCode = "";
            Match curMatch = this.RegexMatch(this.CmdRelayMsg,
                                new String[] { c_REGEX_STR_REPCODE });

            curCode = (curMatch != null ?
                       curMatch.Groups[c_RepCode].Value.ToString() : "");
            return curCode;
        }

        private void CheckCmdStatus(String ComdStatusCode,
                                          String curCmdStr, FtpCodeMsg[] Results)
        {
            bool ret = false;

            curCmdStr = (curCmdStr == null ? "" : curCmdStr);
            if (Results != null && ComdStatusCode != null)
            {

                foreach (FtpCodeMsg curCode in Results)
                {
                    if (ComdStatusCode.Trim().Equals(curCode.Code))
                    {
                        ret = true;
                        break;
                    }
                }
            }

            if (!ret)
            {
                this.DisConnect();

                throw new IOException(
                         String.Format(FtpCommon.ERR_CONNECTERR.toString(),
                                       curCmdStr, this.CmdRelayMsg)
                 );
            }
        }





        private String FormatPathName(String curPathName)
        {

            if (curPathName == null || curPathName.Equals(""))
            {
                curPathName = @"/";
            }


            if (!curPathName.StartsWith(@"/"))
            {
                curPathName = @"/" + curPathName;
            }


            while (true)
            {
                if (curPathName.Length > 0 && curPathName.Contains(@"//"))
                {
                    curPathName = curPathName.Replace(@"//", @"/");
                }
                else
                {
                    break;
                }
            }

            while (true)
            {
                if (curPathName.Length > 1 && curPathName.EndsWith(@"/"))
                {
                    curPathName = curPathName.Remove(curPathName.Length - 1);
                }
                else
                {
                    break;
                }
            }
            return curPathName;
        }

        private String TrcatePath(String pPathname, String cPathName)
        {
            StringBuilder curPath = new StringBuilder();

            if (!FormatPathName(pPathname).Equals(@"/"))
            {
                curPath.Append(FormatPathName(pPathname));
            }

            if (!FormatPathName(cPathName).Equals(@"/"))
            {
                curPath.Append(FormatPathName(cPathName));
            }

            if (curPath.Length <= 0)
            {
                curPath.Append(@"/");
            }
            return curPath.ToString();

        }

        private String GetRemoteAbsolutePath(String strDirName,
                                      FtpRemoteDirOption CkType)
        {
            String curPath = "", curPath2 = "";
            switch (CkType)
            {
                case FtpRemoteDirOption.UrlOpposite:

                    curPath = this.TrcatePath(this.RemoteCurSubDir,
                                 this.RemoteHostUrlSubDir);

                    curPath = this.TrcatePath(curPath, strDirName);

                    this.RemotesubDir = this.FormatPathName(strDirName);
                    break;
                case FtpRemoteDirOption.IpOpposite:

                    curPath = this.TrcatePath(this.RemoteCurSubDir,
                                                       strDirName);


                    curPath2 = this.TrcatePath(this.RemoteCurSubDir,
                                        this.RemoteHostUrlSubDir);

                    if (curPath.StartsWith(curPath2)
                         && curPath2.Length <= curPath.Length
                         && curPath2.Length > 0)
                    {
                        this.RemotesubDir = curPath.Substring(
                                                        curPath2.Length);

                        this.RemotesubDir = this.FormatPathName(this.RemotesubDir);
                    }
                    break;
                case FtpRemoteDirOption.CurWorkDirOpposite:

                    curPath = this.TrcatePath(this.RemoteCurSubDir,
                                 this.RemoteHostUrlSubDir);

                    curPath = this.TrcatePath(curPath, this.RemotesubDir);

                    curPath = this.TrcatePath(curPath, strDirName);

                    this.RemotesubDir = this.TrcatePath(RemotesubDir, strDirName);
                    break;
                case FtpRemoteDirOption.Absolutely:

                    curPath = this.FormatPathName(strDirName);

                    curPath2 = this.TrcatePath(this.RemoteCurSubDir,
                                      this.RemoteHostUrlSubDir);


                    if (curPath.StartsWith(curPath2)
                          && curPath2.Length <= curPath.Length
                          && curPath2.Length > 0)
                    {

                        this.RemotesubDir = curPath.Substring(
                                                       curPath2.Length);

                        this.RemotesubDir = this.FormatPathName(this.RemotesubDir);
                    }
                    else
                    {
                        this.RemotesubDir = "";
                    }
                    break;
            }
            return curPath;
        }

        public void ChangeDir(String strDirName)
        {
            ChangeDir(strDirName,
                   FtpRemoteDirOption.UrlOpposite);
        }

        public void ChangeDir(String strDirName,
                              FtpRemoteDirOption CkType)
        {

            bool retCnt = false;
            while (true)
            {
                try
                {

                    if (!this.Connected)
                    {

                        this.Connect();
                        retCnt = true;
                    }

                    this.StrRemoteAbsolutDir = GetRemoteAbsolutePath(strDirName, CkType);

                    this.ExecCommand(FtpCommon.CMD_CWD,
                           this.RemoteAbsolutDir);
                    break;

                }
                catch (Exception e)
                {

                    if (this.CmdRelayMsg.Equals("") && !retCnt)
                    {

                        ExceptionSleepWaiting();
                        retCnt = !retCnt;

                    }
                    else
                    {
                        throw e;
                    }
                }
            }
        }

        public void ChildDir(String strDirName)
        {
            ChangeDir(strDirName,
                    FtpRemoteDirOption.CurWorkDirOpposite);
        }

        public void CdUpDir()
        {
            String curPath2 = "";

            this.StrRemoteAbsolutDir = FormatPathName(this.RemoteAbsolutDir);

            if (this.StrRemoteAbsolutDir.Equals(@"/"))
            {
                return;
            }
            this.StrRemoteAbsolutDir = this.RemoteAbsolutDir.Substring(0,
                                      this.RemoteAbsolutDir.LastIndexOf(@"/"));

            ChangeDir(this.RemoteAbsolutDir, FtpRemoteDirOption.Absolutely);

            curPath2 = this.TrcatePath(this.RemoteCurSubDir,
                                      this.RemoteHostUrlSubDir);

            if (this.RemoteAbsolutDir.StartsWith(curPath2)
                  && curPath2.Length <= this.RemoteAbsolutDir.Length
                  && curPath2.Length > 0)
            {

                this.RemotesubDir = this.RemoteAbsolutDir.Substring(
                                               curPath2.Length);

                this.RemotesubDir = this.FormatPathName(this.RemotesubDir);
            }
            else
            {
                this.RemotesubDir = "";
            }
        }

        private Socket GetDataSocket()
        {

            Socket dataSocket = null;
            String strErrMsg = "";
            FtpDataTransMode curMode = FtpDataTransMode.Port;

            int curCnt = 2;
            bool ret = false;

            if (this.PasvMode
                  != FtpDataTransMode.All)
            {
                curCnt = 1;
                curMode = this.PasvMode;
            }
            while (true)
            {
                try
                {

                    ret = false;
                    switch (curMode)
                    {
                        case FtpDataTransMode.Pasv:
                            dataSocket = this.GetPasvDataSocket();

                            this.PasvMode = FtpDataTransMode.Pasv;
                            break;
                        case FtpDataTransMode.Port:
                            dataSocket = this.GetPortDataSocket();

                            this.PasvMode = FtpDataTransMode.Port;
                            break;
                    }

                    ret = true;
                    break;
                }
                catch (SocketException e)
                {
                    strErrMsg = String.Format("{0}:{1}", e.ErrorCode, e.Message);
                }
                catch (Exception e)
                {
                    strErrMsg = e.Message;
                }
                finally
                {
                    curCnt--;
                    curMode = (curMode == FtpDataTransMode.Port ?
                        FtpDataTransMode.Pasv : FtpDataTransMode.Port);

                    if (dataSocket == null
                           && curCnt <= 0
                           && !ret)
                    {
                        throw (new Exception(strErrMsg));
                    }

                }
            }
            return dataSocket;
        }

        [DllImport("kernel32.dll")]
        extern static short QueryPerformanceCounter(ref long x);
        [DllImport("kernel32.dll")]
        extern static short QueryPerformanceFrequency(ref long x);


        private void RestoreDataSocket(ref Socket dataSocket)
        {

            if (this.socketListener != null
                && this.PasvMode == FtpDataTransMode.Port)
            {
                socketListener.ReceiveTimeout = 5000;
                socketListener.SendTimeout = 5000;
                dataSocket = this.socketListener.Accept();
                this.socketListener.Close();
                this.socketListener = null;
            }
            //this.Mode == FtpDataTransMode.Pasv 
            if (dataSocket == null)
            {
                throw new Exception("数据传输插口取得失败");
            }
        }

        private int GetFreePort()
        {
            long kk = 0;
            int intFreePort = 0;
            Socket curSocket = null;
            IPEndPoint curendPoint = null;
            Random ran = new Random();
            QueryPerformanceCounter(ref  kk);
            try
            {

                intFreePort = int.Parse(kk.ToString().PadLeft(14, '0').Substring(9));

                if (intFreePort <= 1025)
                {
                    intFreePort += 5000;
                }

                intFreePort = ran.Next(1025, System.Math.Abs((int)intFreePort));
                curSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                curendPoint = new IPEndPoint(IPAddress.Any, intFreePort);
                curSocket.Bind(curendPoint);
                curSocket.Close();
                curSocket = null;
            }
            catch
            {
                if (curSocket != null)
                {
                    curSocket = null;
                }
                intFreePort = GetFreePort();
            }

            if (intFreePort <= 1024)
            {
                Thread.Sleep(100);
                intFreePort = GetFreePort();
            }
            return intFreePort;
        }

        private Socket GetPortDataSocket()
        {
            Match curMath = null;
            String IpAdr = "";
            int IpPort = 0;
            IPEndPoint IpDataPoint = null;

            if (!this.Connected)
            {
                this.Connect();
            }


            this.socketListener = new Socket(AddressFamily.InterNetwork,
                                            SocketType.Stream, ProtocolType.Tcp);


            if ((curMath =
                 this.RegexMatch(this.socketControl.LocalEndPoint.ToString(),
                                 new String[] { c_REGEX_STR_FTPADR })) == null)
            {
                throw new Exception(
                    String.Format(FtpCommon.ERR_GETLOCALIP.toString(),
                       this.socketControl.LocalEndPoint.ToString()));
            }

            IpAdr = curMath.Groups[c_RegexAdr].Value;

            if (this.RegexMatch(IpAdr,
                    new String[] { c_REGEX_STR_IP }) == null)
            {
                throw new Exception(
                    String.Format(FtpCommon.ERR_GETLOCALIP.toString(),
                       this.socketControl.LocalEndPoint.ToString()));
            }

            if (curMath.Groups[c_RegexPort].Value.Equals(""))
            {
                throw new Exception(
                     String.Format(FtpCommon.ERR_GETLOCALIP.toString(),
                        this.socketControl.LocalEndPoint.ToString()));
            }
            IpPort = GetFreePort();

            IpDataPoint = new IPEndPoint(IPAddress.Parse(IpAdr), IpPort);
            this.socketListener.Bind(IpDataPoint);
            this.socketListener.Listen(30);


            IpAdr = IpAdr.Replace(".", ",") + "," + (IpPort / 256) + "," + (IpPort % 256);

            this.ExecCommand(FtpCommon.CMD_PORT, IpAdr);

            return null;
        }

        private Socket GetPasvDataSocket()
        {
            Match curMath = null;
            String IpAdr = "";
            Socket dataSocket = null;
            int Iport = 0;



            if (!this.Connected)
            {
                this.Connect();
            }

            this.ExecCommand(FtpCommon.CMD_PASV);

            curMath =
                   this.RegexMatch(this.CmdRelayMsg,
                       new String[] { c_REGEX_STR_IP_TRANS });

            if (curMath == null
                || !curMath.Success)
            {
                this.DisConnect();
                this.blnErrFlag = false;
                throw new Exception(
                       String.Format(FtpCommon.ERR_GETDATASOCKETERR.toString(),
                                  this.CmdRelayMsg));
            }

            IpAdr = curMath.Groups[c_RegexAdr].Value.Replace(@",", @".");

            if (!curMath.Groups[c_RegexPort].Value.Equals(""))
            {
                Iport += (int.Parse(curMath.Groups[c_RegexPort].Value) << 8);
            }
            if (!curMath.Groups[c_RegexPort1].Value.Equals(""))
            {
                Iport += int.Parse(curMath.Groups[c_RegexPort1].Value);
            }

            dataSocket = new Socket(AddressFamily.InterNetwork,
                                 SocketType.Stream,
                                          ProtocolType.Tcp);
            try
            {

                dataSocket.Connect(new IPEndPoint(IPAddress.Parse(IpAdr),
                                         Iport));

            }
            catch (SocketException e)
            {

                throw e;
            }
            catch (Exception e)
            {
                throw (new Exception(
                             String.Format(FtpCommon.ERR_CREATEDATASOCKETERR.toString(),
                                IpAdr, Iport, e.ToString())));
            }
            return dataSocket;
        }

        public List<FtpFileInfo> GetCurDirList(FtpFileType curType,
                                                    String strMasrkFileName)
        {
            return GetCurDirList(@"/",
                        FtpRemoteDirOption.CurWorkDirOpposite,
                         new FtpFileType[] { curType }, strMasrkFileName);
        }

        public List<FtpFileInfo> GetCurDirList(FtpFileType curType)
        {
            return GetCurDirList(new FtpFileType[] { curType }, "");
        }

        public List<FtpFileInfo> GetCurDirList(FtpFileType[] curType,
                                                    String strMasrkFileName)
        {
            return GetCurDirList(@"/",
                        FtpRemoteDirOption.CurWorkDirOpposite,
                         curType, strMasrkFileName);
        }

        public List<FtpFileInfo> GetCurDirList(FtpFileType[] curType)
        {
            return GetCurDirList(curType, "");
        }

        public List<FtpFileInfo> GetCurDirList(String strFolderName,
                                               FtpRemoteDirOption CkType,
                                               FtpFileType[] FileType,
                                               String strMasrkFileName)
        {

            Socket DataSocket = null;
            int curSize = 0, intCount = 0;
            Byte[] curGetBuffer = new byte[c_BLOCK_SIZE];

            StringBuilder curMsgBuffer = new StringBuilder();
            string curTemp = "";
            //
            List<FtpFileInfo> fileList = new List<FtpFileInfo>();
            List<FtpFileType> curTypeList = new List<FtpFileType>(FileType);

            bool reTry = false;


            while (true)
            {
                try
                {

                    this.ChangeDir(strFolderName, CkType);

                    DataSocket = GetDataSocket();

                    this.ExecCommand(FtpCommon.CMD_LIST,
                                    new String[] { "-AL", strMasrkFileName });

                    RestoreDataSocket(ref DataSocket);

                    while (true)
                    {
                        curSize =
                             DataSocket.Receive(curGetBuffer,
                                    curGetBuffer.Length, 0);
                        curMsgBuffer.Append(
                                  Encoding.UTF8.GetString(curGetBuffer, 0, curSize)
                                       );
                        if (curSize < curGetBuffer.Length)
                        {
                            intCount++;
                            Thread.Sleep(10);
                            if (intCount >= 2)
                            {
                                break;
                            }
                        }
                    }
                    this.ReadCmdReply();

                    CheckCmdStatus(ReturnCode(),
                          this.CmdRelayMsg, new FtpCodeMsg[] { FtpCommon.REP_226 });
                    if (DataSocket.Connected)
                    {
                        DataSocket.Close();
                    }
                    DataSocket = null;

                    if (curMsgBuffer.Length > 0)
                    {
                        string strSplit = c_LF;
                        if (curMsgBuffer.ToString().Contains(c_CTRLF))
                        {
                            strSplit = c_CTRLF;
                        }

                        String[] curFileArry = curMsgBuffer.ToString().Split(strSplit.ToCharArray());

                        foreach (String curStr in curFileArry)
                        {

                            if (curStr.Equals(""))
                            {
                                continue;
                            }
                            Match curMatch = RegexMatch(curStr, c_ListRegexFormats);

                            if (curMatch == null)
                            {
                                continue;
                            }
                            FtpFileInfo curFileInfo = new FtpFileInfo();

                            curFileInfo.FileName = curMatch.Groups[c_RegexName].Value;

                            curFileInfo.Perssion = curMatch.Groups[c_RegexPer].Value;

                            long _size = 0;
                            Int64.TryParse(curMatch.Groups[c_RegexSize].Value, out _size);
                            curFileInfo.fileSize = _size;

                            curFileInfo.FileRemotePath = this.RemoteAbsolutDir;

                            curFileInfo.FileType = FtpFileType.File;
                            if (curMatch.Groups[c_RegexDir].Value != ""
                                 && curMatch.Groups[c_RegexDir].Value != "-")
                            {
                                curFileInfo.FileType = FtpFileType.Directory;
                            }

                            if (curFileInfo.FileName.Equals(""))
                            {
                                curFileInfo.FileType = FtpFileType.Other;
                            }

                            curTemp = curMatch.Groups[c_RegexTime].Value;
                            if (!curTemp.Equals(""))
                            {
                                try
                                {
                                    curFileInfo.ModTime = DateTime.Parse(curTemp);
                                }
                                catch
                                {

                                }
                            }

                            if (curFileInfo.FileType.Equals(FtpFileType.Directory)
                                && this.ChildFolderDown)
                            {
                                this.ChangeDir(curFileInfo.FileName, FtpRemoteDirOption.CurWorkDirOpposite);

                                curFileInfo.FileList = this.GetCurDirList(
                                                       strFolderName,
                                                                 CkType,
                                                                      FileType,
                                                                           strMasrkFileName);
                                this.CdUpDir();
                            }

                            if (curTypeList.FindAll(delegate(FtpFileType key)
                            {
                                return (key.CompareTo(curFileInfo.FileType) == 0);
                            }).Count > 0
                                ||
                              curTypeList.FindAll(delegate(FtpFileType key)
                              {
                                  return (key.CompareTo(FtpFileType.All) == 0);
                              }).Count > 0
                                || curFileInfo.FileList.Count > 0)
                            {
                                fileList.Add(curFileInfo);
                            }
                        }
                    }
                    break;

                }
                catch (Exception e)
                {
                    if (this.CmdRelayMsg.Equals("") && !reTry)
                    {
                        this.ExceptionSleepWaiting();
                        reTry = !reTry;
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
            return fileList;
        }

        public int DownLoad()
        {

            return DownLoad(@"/",
                           FtpRemoteDirOption.CurWorkDirOpposite);
        }

        public int DownLoad(String strRemoteDirName,
                                 FtpRemoteDirOption CkType
                                )
        {
            int curFileCont = 0;

            List<FtpFileInfo> curList = null;
            FtpFileType[] curftpType = new FtpFileType[2];

            this.ChangeDir(strRemoteDirName, CkType);

            curftpType[0] = FtpFileType.File;
            curftpType[1] = FtpFileType.File;

            if (this.ChildFolderDown)
            {
                curftpType[1] = FtpFileType.Directory;
            }

            curList = this.GetCurDirList(curftpType);

            curFileCont += DownLoad(curList, this.LocalDir);
            return curFileCont;
        }

        public int DownLoad(
                             List<FtpFileInfo> fileList,
                             String strParamLocPath)
        {
            int curFileCont = 0;

            if (fileList == null)
            {
                return 0;
            }

            foreach (FtpFileInfo curFIle in fileList)
            {
                switch (curFIle.FileType)
                {
                    case FtpFileType.File:

                        curFileCont += DownLoad(curFIle.FileRemotePath,
                                          curFIle.FilePathType,
                                          curFIle.FileName, strParamLocPath);
                        break;
                    case FtpFileType.Directory:

                        if (!Directory.Exists(Path.Combine(strParamLocPath, curFIle.FileName)))
                        {
                            Directory.CreateDirectory(Path.Combine(strParamLocPath, curFIle.FileName));
                        }

                        if (this.ChildFolderDown)
                        {
                            curFileCont += DownLoad(curFIle.FileList,
                                  Path.Combine(strParamLocPath, curFIle.FileName));
                        }
                        break;
                }

            }
            return curFileCont;
        }

        // static AutoResetEvent autoEvent = new AutoResetEvent(false);

        public int DownLoad(String strRemoteDirName,
                                 FtpRemoteDirOption CkType,
                                 String strFileName,
                                 String strLocalSavePath)
        {
            AutoResetEvent autoEvent = new AutoResetEvent(false);
            String curAbusultePath = "", curLocSavePath = "";

            Socket DataSocket = null;

            FileStream outFileStream = null;
            int curSize = 0;
            Byte[] curGetBuffer = new byte[c_BLOCK_SIZE];

            bool retry = false;

            if (strFileName.Equals(""))
            {
                return 0;
            }

            while (true)
            {
                try
                {

                    DataSocket = this.GetDataSocket();

                    curAbusultePath = this.GetRemoteAbsolutePath(strRemoteDirName, CkType);

                    strLocalSavePath = (strLocalSavePath == null ?
                                               this.LocalDir : strLocalSavePath);
                    curLocSavePath = (strLocalSavePath.Length > 0 ?
                                                       strLocalSavePath :
                                       this.LocalDir);
                    curLocSavePath = (curLocSavePath.Length > 0 ?
                                                       curLocSavePath :
                                       System.IO.Directory.GetCurrentDirectory());

                    if (!Directory.Exists(curLocSavePath))
                    {
                        Directory.CreateDirectory(curLocSavePath);
                    }

                    if (File.Exists(Path.Combine(curLocSavePath, strFileName)))
                    {

                        if (!this.DownLoadOverWrite)
                        {
                            File.Delete(Path.Combine(curLocSavePath, strFileName));
                        }
                        else
                        {
                            return 0;
                        }
                    }
                    ThreadPool.QueueUserWorkItem((o) =>
                    {
                        RestoreDataSocket(ref DataSocket);
                        ((AutoResetEvent)o).Set();
                    }, autoEvent);

                    var str = this.ExecCommand(FtpCommon.CMD_RETR,
                                   this.TrcatePath(curAbusultePath, strFileName)
                                   );
                    var flag = autoEvent.WaitOne(System.Threading.Timeout.Infinite);

                    if (!flag)
                    {
                        if (DataSocket.Connected)
                        {
                            DataSocket.Close();
                        }
                        DataSocket = null;
                        break;
                    }

                    //Utility.Logger.Debug("Execute ftp cmd...");
                    //var str = this.ExecCommand(FtpCommon.CMD_RETR,
                    //               this.TrcatePath(curAbusultePath, strFileName)
                    //               );
                    //Utility.Logger.Debug("Execute ftp cmd end:" + str);

                    //Utility.Logger.Debug("RestoreDataSocket..");
                    //RestoreDataSocket(ref DataSocket);
                    //Utility.Logger.Debug("RestoreDataSocket end");


                    outFileStream = new FileStream(Path.Combine(curLocSavePath, strFileName),
                                                   FileMode.Create);
                    while (true)
                    {
                        curSize =
                             DataSocket.Receive(curGetBuffer,
                                          curGetBuffer.Length, 0);
                        outFileStream.Write(curGetBuffer, 0, curSize);

                        if (curSize <= 0)
                        {
                            break;
                        }
                    }
                    if (outFileStream != null)
                    {
                        outFileStream.Close();
                        outFileStream = null;
                    }
                    this.ReadCmdReply();

                    CheckCmdStatus(ReturnCode(),
                          this.CmdRelayMsg, new FtpCodeMsg[] { FtpCommon.REP_226, 
                                                        FtpCommon.REP_250});
                    if (DataSocket.Connected)
                    {
                        DataSocket.Close();
                    }
                    DataSocket = null;
                    break;

                }
                catch (Exception e)
                {

                    if (this.CmdRelayMsg.Equals("") && !retry)
                    {
                        this.ExceptionSleepWaiting();
                        retry = !retry;
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
            return 1;
        }

        /// <summary>
        /// 上传文件夹 
        /// </summary>
        /// <param name="strRemoteDir">远端路径最后不能包含"/"或"\" 结束符</param>
        /// <param name="strLocalDir">本地路径</param>
        /// <param name="searchPattern">需要匹配的文件</param>
        public void UploadDir(string strRemoteDir, string strLocalDir, string searchPattern = "*.*")
        {
            DirectoryInfo dirinfo = new DirectoryInfo(strLocalDir);
            foreach (var item in dirinfo.GetFiles(searchPattern))
            {
                Upload(strRemoteDir, FtpRemoteDirOption.Absolutely, item.FullName);
            }
            foreach (var item in dirinfo.GetDirectories())
            {
                MkDir(strRemoteDir, FtpRemoteDirOption.Absolutely, item.Name);
                UploadDir(strRemoteDir == "/" ? "/" + item.Name : strRemoteDir + "/" + item.Name, item.FullName, searchPattern);
            }
        }
        public void UploadDir(string strLocalDir, string searchPattern = "*.*")
        {
            UploadDir("/", strLocalDir, searchPattern);
        }

        public void UploadDir(string strLocalDir)
        {
            UploadDir("/", strLocalDir, "*.*");
        }

        public void Upload(String strLocalFileFullName)
        {
            FileInfo curFile = new FileInfo(strLocalFileFullName);

            Upload(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite,
                   strLocalFileFullName,
                   curFile.Name);
        }

        public void Upload(String strLocalFileFullName,
                           String strRemoteFileName)
        {

            FileInfo curFile = new FileInfo(strLocalFileFullName);

            Upload(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite,
                   strLocalFileFullName,
                   strRemoteFileName);
        }

        public void Upload(String strRemoteDirName,
                           FtpRemoteDirOption CkType,
                           String strLocalFileFullName
                          )
        {
            FileInfo curFile = new FileInfo(strLocalFileFullName);
            Upload(strRemoteDirName,
                  CkType,
                  strLocalFileFullName,
                   curFile.Name);
        }

        public void Upload(String strRemoteDirName,
                           FtpRemoteDirOption CkType,
                           String strLocalFileFullName,
                           String strRemoteFileName
                           )
        {

            String curAbusultePath = "";

            Socket DataSocket = null;

            FileStream outFileStream = null;
            bool retry = false;

            int curSize = 0;
            Byte[] curGetBuffer = new byte[c_BLOCK_SIZE];


            if (strLocalFileFullName.Equals("")
                || !File.Exists(strLocalFileFullName)
                || strRemoteFileName.Equals(""))
            {
                return;
            }
            while (true)
            {
                try
                {
                    AutoResetEvent autoEvent = new AutoResetEvent(false);
                    DataSocket = this.GetDataSocket();

                    curAbusultePath = this.GetRemoteAbsolutePath(strRemoteDirName, CkType);

                    if (!curAbusultePath.Equals(this.RemoteAbsolutDir))
                    {
                        //this.ChangeDir(strRemoteDirName, CkType);
                    }

                    ThreadPool.QueueUserWorkItem((o) =>
                    {
                        RestoreDataSocket(ref DataSocket);
                        ((AutoResetEvent)o).Set();
                    }, autoEvent);

                    this.ExecCommand(FtpCommon.CMD_STOR,
                          this.TrcatePath(curAbusultePath, strRemoteFileName));

                    if (!autoEvent.WaitOne(3000))
                    {
                        if (DataSocket.Connected)
                        {
                            DataSocket.Close();
                            DataSocket = null;
                        }
                        break;
                    }
                    //RestoreDataSocket(ref DataSocket);

                    outFileStream = new FileStream(strLocalFileFullName,
                                                         FileMode.Open,
                                                         FileAccess.Read);
                    BinaryReader binreader = new BinaryReader(outFileStream, Encoding.UTF8);

                    while (true)
                    {
                        // curSize = outFileStream.Read(curGetBuffer, 0, curGetBuffer.Length);

                        curSize = binreader.Read(curGetBuffer, 0, curGetBuffer.Length);

                        if (curSize <= 0)
                        {
                            break;
                        }

                        DataSocket.Send(curGetBuffer, curSize, 0);
                    }
                    if (outFileStream != null)
                    {
                        outFileStream.Close();
                        outFileStream = null;
                        binreader.Close();
                        binreader = null;
                    }
                    if (DataSocket.Connected)
                    {
                        DataSocket.Close();
                        DataSocket = null;
                    }
                    this.ReadCmdReply();

                    CheckCmdStatus(ReturnCode(),
                          this.CmdRelayMsg, new FtpCodeMsg[] { FtpCommon.REP_226, 
                                                        FtpCommon.REP_250});
                    break;

                }
                catch (Exception e)
                {
                    if (this.CmdRelayMsg.Equals("") && !retry)
                    {
                        this.ExceptionSleepWaiting();
                        retry = !retry;
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
        }

        public void ReName(String strOldeFileName,
                                String strNewFIleName)
        {

            this.ReName(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite,
                           strOldeFileName,
                           strNewFIleName);
        }

        public void ReName(
                                String strReMoteDir,
                                FtpRemoteDirOption ckDirOpt,
                                String strOldeFileName,
                                String strNewFIleName)
        {
            String curAuDir = "";

            if (!this.Connected)
            {
                this.Connect();
            }

            if (strOldeFileName.Equals("")
                 || strNewFIleName.Equals("")
                 || strOldeFileName.Contains(@"/")
                || strNewFIleName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_RENAMEFILE_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteDir, ckDirOpt);

            this.ExecCommand(FtpCommon.CMD_RNFR, this.TrcatePath
                               (curAuDir, strOldeFileName)
                               );

            if (this.ReturnCode().Equals(FtpCommon.REP_550.Code))
            {
                return;
            }

            this.ExecCommand(FtpCommon.CMD_RNTO, this.TrcatePath
                               (curAuDir, strNewFIleName));
        }

        public void Delete(String FileName)
        {

            this.Delete(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite,
                      FileName);
        }

        public void Delete(String strReMoteDir,
                                FtpRemoteDirOption ckDirOpt,
                                String FileName)
        {
            String curAuDir = "";

            if (!this.Connected)
            {
                this.Connect();
            }

            if (FileName.Equals("") || FileName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_PARAM_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteDir, ckDirOpt);

            this.ExecCommand(FtpCommon.CMD_DELE, this.TrcatePath
                               (curAuDir, FileName)
                               );

        }


        public void MkDir(String strNewDirName)
        {

            this.MkDir(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite,
                     strNewDirName);
        }

        public void MkDir(String strReMoteParDir,
                            FtpRemoteDirOption ckDirOpt,
                            String strNewDirName)
        {
            String curAuDir = "";

            if (!this.Connected)
            {
                this.Connect();
            }

            if (strNewDirName.Equals("") || strNewDirName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_PARAM_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteParDir, ckDirOpt);

            this.ExecCommand(FtpCommon.CMD_CWD_MKD,
                             this.TrcatePath(curAuDir,
                                             strNewDirName));

            if (this.ReturnCode().Equals(FtpCommon.REP_250))
            {

                this.CdUpDir();
                return;
            }

            this.ExecCommand(FtpCommon.CMD_MKD, this.TrcatePath
                               (curAuDir, strNewDirName)
                               );
        }


        public void DelDir(String strDirName)
        {

            this.DelDir(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite, strDirName);
        }

        public void DelDir(String strReMoteParDir,
                            FtpRemoteDirOption ckDirOpt,
                            String strDirName)
        {
            String curAuDir = "";
            bool blnChildDown = this.ChildFolderDown;
            List<FtpFileInfo> curList = null;

            if (!this.Connected)
            {
                this.Connect();
            }

            if (strDirName.Equals("") || strDirName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_PARAM_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteParDir, ckDirOpt);
            try
            {

                this.ChangeDir(this.TrcatePath
                        (curAuDir, strDirName),
                        FtpRemoteDirOption.Absolutely);

                this.ChildFolderDown = false;

                curList = this.GetCurDirList(new FtpFileType[]{
                                                FtpFileType.File,
                                                FtpFileType.Directory});

                this.ChildFolderDown = blnChildDown;
                if (curList != null && curList.Count > 0)
                {
                    foreach (FtpFileInfo curFile in curList)
                    {
                        switch (curFile.FileType)
                        {
                            case FtpFileType.File:
                                this.Delete(curFile.FileRemotePath,
                                     curFile.FilePathType,
                                     curFile.FileName);
                                break;
                            case FtpFileType.Directory:
                                this.DelDir(curFile.FileRemotePath,
                                     curFile.FilePathType,
                                     curFile.FileName);
                                break;
                        }
                    }
                }

                this.CdUpDir();
            }
            catch
            {
                return;
            }

            this.ExecCommand(FtpCommon.CMD_RMD, this.TrcatePath
                               (curAuDir, strDirName)
                               );
        }


        public void Noop()
        {

            if (!this.Connected)
            {
                this.Connect();
            }
            this.ExecCommand(FtpCommon.CMD_NOOP);
        }


        public int Size(
                            String strFileName)
        {
            return Size(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite, strFileName);
        }

        public int Size(String strReMoteParDir,
                            FtpRemoteDirOption ckDirOpt,
                            String strFileName)
        {
            String curAuDir = "";
            Match curMatch = null;
            int curSize = 0;

            if (!this.Connected)
            {
                this.Connect();
            }

            if (strFileName.Equals("") || strFileName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_PARAM_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteParDir, ckDirOpt);

            this.ExecCommand(FtpCommon.CMD_SIZE,
                             this.TrcatePath(curAuDir,
                                             strFileName));

            curMatch = this.RegexMatch(this.CmdRelayMsg,
                              new String[] {
                               @"\s(?<Size>\d+)"});
            if (curMatch != null)
            {
                curSize = int.Parse(curMatch.Groups["Size"].Value);
            }
            return curSize;
        }

        public DateTime ModTime(
                            String strFileName)
        {
            return ModTime(@"/",
                    FtpRemoteDirOption.CurWorkDirOpposite, strFileName);
        }

        public DateTime ModTime(String strReMoteParDir,
                            FtpRemoteDirOption ckDirOpt,
                            String strFileName)
        {
            String curAuDir = "";
            Match curMatch = null;
            DateTime curModTime = default(DateTime);

            if (!this.Connected)
            {
                this.Connect();
            }

            if (strFileName.Equals("") || strFileName.Contains(@"/"))
            {
                throw new Exception(FtpCommon.ERR_PARAM_ISNULL.toString());
            }

            curAuDir = this.GetRemoteAbsolutePath(strReMoteParDir, ckDirOpt);

            this.ExecCommand(FtpCommon.CMD_MDTM,
                             this.TrcatePath(curAuDir,
                                             strFileName));


            curMatch = this.RegexMatch(this.CmdRelayMsg,
                              new String[] {
                               @"\s+(?<Year>\d{4})(?<Month>\d{2})(?<Day>\d{2})(?<Time>\d{2})(?<Min>\d{2})(?<Sec>\d{2})"});
            if (curMatch != null)
            {
                try
                {
                    //年
                    curAuDir = curMatch.Groups["Year"].Value;
                    //月
                    curAuDir += @"/" + curMatch.Groups["Month"].Value;
                    //日
                    curAuDir += @"/" + curMatch.Groups["Day"].Value;
                    //時
                    curAuDir += " " + curMatch.Groups["Time"].Value;
                    //分
                    curAuDir += ":" + curMatch.Groups["Min"].Value;
                    //秒
                    curAuDir += ":" + curMatch.Groups["Sec"].Value;
                    curModTime = DateTime.Parse(curAuDir);
                }
                catch
                {
                }
            }
            return curModTime;
        }



        public String Help()
        {

            if (!this.Connected)
            {
                this.Connect();
            }

            this.ExecCommand(FtpCommon.CMD_HELP);


            return this.CmdRelayFullMsg;
        }

        private Match RegexMatch(String strValue, String[] RegexStr)
        {
            //Regex curRegex;
            Match curMatch = null;

            if (RegexStr != null)
            {
                foreach (String curStr in RegexStr)
                {
                    if (!curStr.Equals(""))
                    {
                        //curRegex = new Regex();
                        curMatch = Regex.Match(strValue, curStr);
                        //OK
                        if (curMatch.Success)
                        {
                            return curMatch;
                        }
                    }
                }
            }
            return null;
        }

    }
}
